home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / Python-1.4 / Lib / quopri.py < prev    next >
Text File  |  1998-06-24  |  3KB  |  134 lines

  1. # Conversions to/from quoted-printable transport encoding as per RFC-XXXX
  2. # (Dec 1991 version).
  3.  
  4. ESCAPE = '='
  5. MAXLINESIZE = 76
  6. HEX = '0123456789ABCDEF'
  7.  
  8. def needsquoting(c, quotetabs):
  9.     if c == '\t':
  10.         return not quotetabs
  11.     return c == ESCAPE or not(' ' <= c <= '~')
  12.  
  13. def quote(c):
  14.     if c == ESCAPE:
  15.         return ESCAPE * 2
  16.     else:
  17.         i = ord(c)
  18.         return ESCAPE + HEX[i/16] + HEX[i%16]
  19.  
  20. def encode(input, output, quotetabs):
  21.     while 1:
  22.         line = input.readline()
  23.         if not line: break
  24.         new = ''
  25.         last = line[-1:]
  26.         if last == '\n': line = line[:-1]
  27.         else: last = ''
  28.         prev = ''
  29.         for c in line:
  30.             if needsquoting(c, quotetabs):
  31.                 c = quote(c)
  32.             if len(new) + len(c) >= MAXLINESIZE:
  33.                 output.write(new + ESCAPE + '\n')
  34.                 new = ''
  35.             new = new + c
  36.             prev = c
  37.         if prev in (' ', '\t'):
  38.             output.write(new + ESCAPE + '\n\n')
  39.         else:
  40.             output.write(new + '\n')
  41.  
  42. def decode(input, output):
  43.     new = ''
  44.     while 1:
  45.         line = input.readline()
  46.         if not line: break
  47.         i, n = 0, len(line)
  48.         if n > 0 and line[n-1] == '\n':
  49.             partial = 0; n = n-1
  50.             # Strip trailing whitespace
  51.             while n > 0 and line[n-1] in (' ', '\t'):
  52.                 n = n-1
  53.         else:
  54.             partial = 1
  55.         while i < n:
  56.             c = line[i]
  57.             if c <> ESCAPE:
  58.                 new = new + c; i = i+1
  59.             elif i+1 == n and not partial:
  60.                 partial = 1; break
  61.             elif i+1 < n and line[i+1] == ESCAPE:
  62.                 new = new + ESCAPE; i = i+2
  63.             elif i+2 < n and ishex(line[i+1]) and ishex(line[i+2]):
  64.                 new = new + chr(unhex(line[i+1:i+3])); i = i+3
  65.             else: # Bad escape sequence -- leave it in
  66.                 new = new + c; i = i+1
  67.         if not partial:
  68.             output.write(new + '\n')
  69.             new = ''
  70.     if new:
  71.         output.write(new)
  72.  
  73. def ishex(c):
  74.     return '0' <= c <= '9' or 'a' <= c <= 'f' or 'A' <= c <= 'F'
  75.  
  76. def unhex(s):
  77.     bits = 0
  78.     for c in s:
  79.         if '0' <= c <= '9':
  80.             i = ord('0')
  81.         elif 'a' <= c <= 'f':
  82.             i = ord('a')-10
  83.         elif 'A' <= c <= 'F':
  84.             i = ord('A')-10
  85.         else:
  86.             break
  87.         bits = bits*16 + (ord(c) - i)
  88.     return bits
  89.  
  90. def test():
  91.     import sys
  92.     import getopt
  93.     try:
  94.         opts, args = getopt.getopt(sys.argv[1:], 'td')
  95.     except getopt.error, msg:
  96.         sys.stdout = sys.stderr
  97.         print msg
  98.         print "usage: quopri [-t | -d] [file] ..."
  99.         print "-t: quote tabs"
  100.         print "-d: decode; default encode"
  101.         sys.exit(2)
  102.     deco = 0
  103.     tabs = 0
  104.     for o, a in opts:
  105.         if o == '-t': tabs = 1
  106.         if o == '-d': deco = 1
  107.     if tabs and deco:
  108.         sys.stdout = sys.stderr
  109.         print "-t and -d are mutually exclusive"
  110.         sys.exit(2)
  111.     if not args: args = ['-']
  112.     sts = 0
  113.     for file in args:
  114.         if file == '-':
  115.         fp = sys.stdin
  116.         else:
  117.         try:
  118.             fp = open(file)
  119.         except IOError, msg:
  120.             sys.stderr.write("%s: can't open (%s)\n" % (file, msg))
  121.             sts = 1
  122.             continue
  123.         if deco:
  124.         decode(fp, sys.stdout)
  125.         else:
  126.         encode(fp, sys.stdout, tabs)
  127.         if fp is not sys.stdin:
  128.         fp.close()
  129.     if sts:
  130.         sys.exit(sts)
  131.  
  132. if __name__ == '__main__':
  133.     test()
  134.